package com.darren.archive.controller;


import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: darren
 * @Date: 2020/01/21 12:16
 */
@RestController
public class RestfulApiController {

    @Autowired
    WebApplicationContext applicationContext;

    @GetMapping("/system/api")
    public Object getAllRequestMapping() {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);

        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> handlerMethodsMap = mapping.getHandlerMethods();

        List<Map<String, Object>> list = new ArrayList();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> handlerMethodEntry : handlerMethodsMap.entrySet()) {
            Map<String, Object> requestMapping = new LinkedHashMap<String, Object>();
            RequestMappingInfo requestMappingInfo = handlerMethodEntry.getKey();
            HandlerMethod handlerMethod = handlerMethodEntry.getValue();

            // swagger 接口分组
            Api api = handlerMethod.getMethod().getDeclaringClass().getAnnotation(Api.class);
            if (api != null && api.value() != null) {//权限描述符
                requestMapping.put("接口分组", api.value() == null ? api.tags() : api.value());
            } else {
                requestMapping.put("接口分组", "");
            }

            // 接口 url
            PatternsRequestCondition patternsCondition = requestMappingInfo.getPatternsCondition();
            if (patternsCondition != null && patternsCondition.getPatterns() != null) {
                requestMapping.put("接口 URL", patternsCondition.getPatterns());
            } else {
                requestMapping.put("接口 URL", null);
            }

            //Swagger 接口描述信息，如果有
            ApiOperation apiOperation = handlerMethod.getMethodAnnotation(ApiOperation.class);
            if (apiOperation != null) {//接口描述
                requestMapping.put("接口描述", apiOperation.value() == null ? apiOperation.notes() : apiOperation.value());
            } else {
                requestMapping.put("接口描述", "");
            }

            //Shiro 权限标识
            RequiresPermissions requiresPermissions = handlerMethod.getMethodAnnotation(RequiresPermissions.class);
            if (requiresPermissions != null && requiresPermissions.value() != null) {//权限描述符
                requestMapping.put("权限标识", requiresPermissions.value());
            } else {
                requestMapping.put("权限标识", new ArrayList<String>());
            }

            // java 类全名(包括包路径)
            requestMapping.put("类    名", handlerMethod.getMethod().getDeclaringClass().getName()); // 类名
            //java 方法名
            requestMapping.put("方法名称", handlerMethod.getMethod().getName()); // 方法名

            // 接口 http 方法
            RequestMethodsRequestCondition methodsCondition = requestMappingInfo.getMethodsCondition();
            for (RequestMethod requestMethod : methodsCondition.getMethods()) {
                requestMapping.put("请求方式", requestMethod.toString());
            }
            list.add(requestMapping);
        }
//        list.sort((Map<String, Object> element1, Map<String, Object> element2) -> element1.get("类    名").toString().compareTo(element2.get("类    名").toString()));

        Collections.sort(list, new Comparator<Map<String,Object>>() {
            @Override
            public int compare(Map<String,Object> element1, Map<String,Object> element2) {
                if(element2.get("接口分组").toString().compareTo(element1.get("接口分组").toString()) != 0)
                    return element2.get("接口分组").toString().compareTo(element1.get("接口分组").toString());
                else
                    return element1.get("类    名").toString().compareTo(element2.get("类    名").toString());
            }
        });

        return list;
    }
}
